home *** CD-ROM | disk | FTP | other *** search
/ PC/CD Gamer UK 120 / CD Gamer Issue 120 (March 2003) (Disc 2).ISO / mods / Q2_Codered / codeRED1_0.exe / Data1.cab / g_cmds.c1 < prev    next >
Encoding:
Text File  |  2002-09-13  |  19.1 KB  |  996 lines

  1. /*
  2. Copyright (C) 1997-2001 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. #include "g_local.h"
  21. #include "m_player.h"
  22.  
  23.  
  24. char *ClientTeam (edict_t *ent)
  25. {
  26.     char        *p;
  27.     static char    value[512];
  28.  
  29.     value[0] = 0;
  30.  
  31.     if (!ent->client)
  32.         return value;
  33.  
  34.     strcpy(value, Info_ValueForKey (ent->client->pers.userinfo, "skin"));
  35.     p = strchr(value, '/');
  36.     if (!p)
  37.         return value;
  38.  
  39.     if ((int)(dmflags->value) & DF_MODELTEAMS)
  40.     {
  41.         *p = 0;
  42.         return value;
  43.     }
  44.  
  45.     // if ((int)(dmflags->value) & DF_SKINTEAMS)
  46.     return ++p;
  47. }
  48.  
  49. qboolean OnSameTeam (edict_t *ent1, edict_t *ent2)
  50. {
  51.     char    ent1Team [512];
  52.     char    ent2Team [512];
  53.  
  54.     if (!((int)(dmflags->value) & (DF_MODELTEAMS | DF_SKINTEAMS)))
  55.         return false;
  56.  
  57.     strcpy (ent1Team, ClientTeam (ent1));
  58.     strcpy (ent2Team, ClientTeam (ent2));
  59.  
  60.     if (strcmp(ent1Team, ent2Team) == 0)
  61.         return true;
  62.     return false;
  63. }
  64.  
  65.  
  66. void SelectNextItem (edict_t *ent, int itflags)
  67. {
  68.     gclient_t    *cl;
  69.     int            i, index;
  70.     gitem_t        *it;
  71.  
  72.     cl = ent->client;
  73.  
  74.     if (cl->chase_target) {
  75.         ChaseNext(ent);
  76.         return;
  77.     }
  78.  
  79.     // scan  for the next valid one
  80.     for (i=1 ; i<=MAX_ITEMS ; i++)
  81.     {
  82.         index = (cl->pers.selected_item + i)%MAX_ITEMS;
  83.         if (!cl->pers.inventory[index])
  84.             continue;
  85.         it = &itemlist[index];
  86.         if (!it->use)
  87.             continue;
  88.         if (!(it->flags & itflags))
  89.             continue;
  90.  
  91.         cl->pers.selected_item = index;
  92.         return;
  93.     }
  94.  
  95.     cl->pers.selected_item = -1;
  96. }
  97.  
  98. void SelectPrevItem (edict_t *ent, int itflags)
  99. {
  100.     gclient_t    *cl;
  101.     int            i, index;
  102.     gitem_t        *it;
  103.  
  104.     cl = ent->client;
  105.  
  106.     if (cl->chase_target) {
  107.         ChasePrev(ent);
  108.         return;
  109.     }
  110.  
  111.     // scan  for the next valid one
  112.     for (i=1 ; i<=MAX_ITEMS ; i++)
  113.     {
  114.         index = (cl->pers.selected_item + MAX_ITEMS - i)%MAX_ITEMS;
  115.         if (!cl->pers.inventory[index])
  116.             continue;
  117.         it = &itemlist[index];
  118.         if (!it->use)
  119.             continue;
  120.         if (!(it->flags & itflags))
  121.             continue;
  122.  
  123.         cl->pers.selected_item = index;
  124.         return;
  125.     }
  126.  
  127.     cl->pers.selected_item = -1;
  128. }
  129.  
  130. void ValidateSelectedItem (edict_t *ent)
  131. {
  132.     gclient_t    *cl;
  133.  
  134.     cl = ent->client;
  135.  
  136.     if (cl->pers.inventory[cl->pers.selected_item])
  137.         return;        // valid
  138.  
  139.     SelectNextItem (ent, -1);
  140. }
  141.  
  142.  
  143. //=================================================================================
  144.  
  145. /*
  146. ==================
  147. Cmd_Give_f
  148.  
  149. Give items to a client
  150. ==================
  151. */
  152. void Cmd_Give_f (edict_t *ent)
  153. {
  154.     char        *name;
  155.     gitem_t        *it;
  156.     int            index;
  157.     int            i;
  158.     qboolean    give_all;
  159.     edict_t        *it_ent;
  160.  
  161.     if (deathmatch->value && !sv_cheats->value)
  162.     {
  163.         gi.cprintf (ent, PRINT_HIGH, "You must run the server with '+set cheats 1' to enable this command.\n");
  164.         return;
  165.     }
  166.  
  167.     name = gi.args();
  168.  
  169.     if (Q_stricmp(name, "all") == 0)
  170.         give_all = true;
  171.     else
  172.         give_all = false;
  173.  
  174.     if (give_all || Q_stricmp(gi.argv(1), "health") == 0)
  175.     {
  176.         if (gi.argc() == 3)
  177.             ent->health = atoi(gi.argv(2));
  178.         else
  179.             ent->health = ent->max_health;
  180.         if (!give_all)
  181.             return;
  182.     }
  183.  
  184.     if (give_all || Q_stricmp(name, "weapons") == 0)
  185.     {
  186.         for (i=0 ; i<game.num_items ; i++)
  187.         {
  188.             it = itemlist + i;
  189.             if (!it->pickup)
  190.                 continue;
  191.             if (!(it->flags & IT_WEAPON))
  192.                 continue;
  193.             ent->client->pers.inventory[i] += 1;
  194.         }
  195.         if (!give_all)
  196.             return;
  197.     }
  198.  
  199.     if (give_all || Q_stricmp(name, "ammo") == 0)
  200.     {
  201.         for (i=0 ; i<game.num_items ; i++)
  202.         {
  203.             it = itemlist + i;
  204.             if (!it->pickup)
  205.                 continue;
  206.             if (!(it->flags & IT_AMMO))
  207.                 continue;
  208.             Add_Ammo (ent, it, 1000);
  209.         }
  210.         if (!give_all)
  211.             return;
  212.     }
  213.  
  214.     if (give_all || Q_stricmp(name, "armor") == 0)
  215.     {
  216.         gitem_armor_t    *info;
  217.  
  218.         it = FindItem("Jacket Armor");
  219.         ent->client->pers.inventory[ITEM_INDEX(it)] = 0;
  220.  
  221.         it = FindItem("Combat Armor");
  222.         ent->client->pers.inventory[ITEM_INDEX(it)] = 0;
  223.  
  224.         it = FindItem("Body Armor");
  225.         info = (gitem_armor_t *)it->info;
  226.         ent->client->pers.inventory[ITEM_INDEX(it)] = info->max_count;
  227.  
  228.         if (!give_all)
  229.             return;
  230.     }
  231.  
  232.     if (give_all || Q_stricmp(name, "Power Shield") == 0)
  233.     {
  234.         it = FindItem("Power Shield");
  235.         it_ent = G_Spawn();
  236.         it_ent->classname = it->classname;
  237.         SpawnItem (it_ent, it);
  238.         Touch_Item (it_ent, ent, NULL, NULL);
  239.         if (it_ent->inuse)
  240.             G_FreeEdict(it_ent);
  241.  
  242.         if (!give_all)
  243.             return;
  244.     }
  245.  
  246.     if (give_all)
  247.     {
  248.         for (i=0 ; i<game.num_items ; i++)
  249.         {
  250.             it = itemlist + i;
  251.             if (!it->pickup)
  252.                 continue;
  253.             if (it->flags & (IT_ARMOR|IT_WEAPON|IT_AMMO))
  254.                 continue;
  255.             ent->client->pers.inventory[i] = 1;
  256.         }
  257.         return;
  258.     }
  259.  
  260.     it = FindItem (name);
  261.     if (!it)
  262.     {
  263.         name = gi.argv(1);
  264.         it = FindItem (name);
  265.         if (!it)
  266.         {
  267.             gi.cprintf (ent, PRINT_HIGH, "unknown item\n");
  268.             return;
  269.         }
  270.     }
  271.  
  272.     if (!it->pickup)
  273.     {
  274.         gi.cprintf (ent, PRINT_HIGH, "non-pickup item\n");
  275.         return;
  276.     }
  277.  
  278.     index = ITEM_INDEX(it);
  279.  
  280.     if (it->flags & IT_AMMO)
  281.     {
  282.         if (gi.argc() == 3)
  283.             ent->client->pers.inventory[index] = atoi(gi.argv(2));
  284.         else
  285.             ent->client->pers.inventory[index] += it->quantity;
  286.     }
  287.     else
  288.     {
  289.         it_ent = G_Spawn();
  290.         it_ent->classname = it->classname;
  291.         SpawnItem (it_ent, it);
  292.         Touch_Item (it_ent, ent, NULL, NULL);
  293.         if (it_ent->inuse)
  294.             G_FreeEdict(it_ent);
  295.     }
  296. }
  297.  
  298.  
  299. /*
  300. ==================
  301. Cmd_God_f
  302.  
  303. Sets client to godmode
  304.  
  305. argv(0) god
  306. ==================
  307. */
  308. void Cmd_God_f (edict_t *ent)
  309. {
  310.     char    *msg;
  311.  
  312.     if (deathmatch->value && !sv_cheats->value)
  313.     {
  314.         gi.cprintf (ent, PRINT_HIGH, "You must run the server with '+set cheats 1' to enable this command.\n");
  315.         return;
  316.     }
  317.  
  318.     ent->flags ^= FL_GODMODE;
  319.     if (!(ent->flags & FL_GODMODE) )
  320.         msg = "godmode OFF\n";
  321.     else
  322.         msg = "godmode ON\n";
  323.  
  324.     gi.cprintf (ent, PRINT_HIGH, msg);
  325. }
  326.  
  327.  
  328. /*
  329. ==================
  330. Cmd_Notarget_f
  331.  
  332. Sets client to notarget
  333.  
  334. argv(0) notarget
  335. ==================
  336. */
  337. void Cmd_Notarget_f (edict_t *ent)
  338. {
  339.     char    *msg;
  340.  
  341.     if (deathmatch->value && !sv_cheats->value)
  342.     {
  343.         gi.cprintf (ent, PRINT_HIGH, "You must run the server with '+set cheats 1' to enable this command.\n");
  344.         return;
  345.     }
  346.  
  347.     ent->flags ^= FL_NOTARGET;
  348.     if (!(ent->flags & FL_NOTARGET) )
  349.         msg = "notarget OFF\n";
  350.     else
  351.         msg = "notarget ON\n";
  352.  
  353.     gi.cprintf (ent, PRINT_HIGH, msg);
  354. }
  355.  
  356.  
  357. /*
  358. ==================
  359. Cmd_Noclip_f
  360.  
  361. argv(0) noclip
  362. ==================
  363. */
  364. void Cmd_Noclip_f (edict_t *ent)
  365. {
  366.     char    *msg;
  367.  
  368.     if (deathmatch->value && !sv_cheats->value)
  369.     {
  370.         gi.cprintf (ent, PRINT_HIGH, "You must run the server with '+set cheats 1' to enable this command.\n");
  371.         return;
  372.     }
  373.  
  374.     if (ent->movetype == MOVETYPE_NOCLIP)
  375.     {
  376.         ent->movetype = MOVETYPE_WALK;
  377.         msg = "noclip OFF\n";
  378.     }
  379.     else
  380.     {
  381.         ent->movetype = MOVETYPE_NOCLIP;
  382.         msg = "noclip ON\n";
  383.     }
  384.  
  385.     gi.cprintf (ent, PRINT_HIGH, msg);
  386. }
  387.  
  388.  
  389. /*
  390. ==================
  391. Cmd_Use_f
  392.  
  393. Use an inventory item
  394. ==================
  395. */
  396. void Cmd_Use_f (edict_t *ent)
  397. {
  398.     int            index;
  399.     gitem_t        *it;
  400.     char        *s;
  401.  
  402.     s = gi.args();
  403.     it = FindItem (s);
  404.     if (!it)
  405.     {
  406.         gi.cprintf (ent, PRINT_HIGH, "unknown item: %s\n", s);
  407.         return;
  408.     }
  409.     if (!it->use)
  410.     {
  411.         gi.cprintf (ent, PRINT_HIGH, "Item is not usable.\n");
  412.         return;
  413.     }
  414.     index = ITEM_INDEX(it);
  415.     if (!ent->client->pers.inventory[index])
  416.     {
  417.         gi.cprintf (ent, PRINT_HIGH, "Out of item: %s\n", s);
  418.         return;
  419.     }
  420.  
  421.     it->use (ent, it);
  422. }
  423.  
  424.  
  425. /*
  426. ==================
  427. Cmd_Drop_f
  428.  
  429. Drop an inventory item
  430. ==================
  431. */
  432. void Cmd_Drop_f (edict_t *ent)
  433. {
  434.     int            index;
  435.     gitem_t        *it;
  436.     char        *s;
  437.  
  438.     s = gi.args();
  439.     it = FindItem (s);
  440.     if (!it)
  441.     {
  442.         gi.cprintf (ent, PRINT_HIGH, "unknown item: %s\n", s);
  443.         return;
  444.     }
  445.     if (!it->drop)
  446.     {
  447.         gi.cprintf (ent, PRINT_HIGH, "Item is not dropable.\n");
  448.         return;
  449.     }
  450.     index = ITEM_INDEX(it);
  451.     if (!ent->client->pers.inventory[index])
  452.     {
  453.         gi.cprintf (ent, PRINT_HIGH, "Out of item: %s\n", s);
  454.         return;
  455.     }
  456.  
  457.     it->drop (ent, it);
  458. }
  459.  
  460.  
  461. /*
  462. =================
  463. Cmd_Inven_f
  464. =================
  465. */
  466. void Cmd_Inven_f (edict_t *ent)
  467. {
  468.     int            i;
  469.     gclient_t    *cl;
  470.  
  471.     cl = ent->client;
  472.  
  473.     cl->showscores = false;
  474.     cl->showhelp = false;
  475.  
  476.     if (cl->showinventory)
  477.     {
  478.         cl->showinventory = false;
  479.         return;
  480.     }
  481.  
  482.     cl->showinventory = true;
  483.  
  484.     gi.WriteByte (svc_inventory);
  485.     for (i=0 ; i<MAX_ITEMS ; i++)
  486.     {
  487.         gi.WriteShort (cl->pers.inventory[i]);
  488.     }
  489.     gi.unicast (ent, true);
  490. }
  491.  
  492. /*
  493. =================
  494. Cmd_InvUse_f
  495. =================
  496. */
  497. void Cmd_InvUse_f (edict_t *ent)
  498. {
  499.     gitem_t        *it;
  500.  
  501.     ValidateSelectedItem (ent);
  502.  
  503.     if (ent->client->pers.selected_item == -1)
  504.     {
  505.         gi.cprintf (ent, PRINT_HIGH, "No item to use.\n");
  506.         return;
  507.     }
  508.  
  509.     it = &itemlist[ent->client->pers.selected_item];
  510.     if (!it->use)
  511.     {
  512.         gi.cprintf (ent, PRINT_HIGH, "Item is not usable.\n");
  513.         return;
  514.     }
  515.     it->use (ent, it);
  516. }
  517.  
  518. /*
  519. =================
  520. Cmd_WeapPrev_f
  521. =================
  522. */
  523. void Cmd_WeapPrev_f (edict_t *ent)
  524. {
  525.     gclient_t    *cl;
  526.     int            i, index;
  527.     gitem_t        *it;
  528.     int            selected_weapon;
  529.  
  530.     cl = ent->client;
  531.  
  532.     if (!cl->pers.weapon)
  533.         return;
  534.  
  535.     selected_weapon = ITEM_INDEX(cl->pers.weapon);
  536.  
  537.     // scan  for the next valid one
  538.     for (i=1 ; i<=MAX_ITEMS ; i++)
  539.     {
  540.         index = (selected_weapon + i)%MAX_ITEMS;
  541.         if (!cl->pers.inventory[index])
  542.             continue;
  543.         it = &itemlist[index];
  544.         if (!it->use)
  545.             continue;
  546.         if (! (it->flags & IT_WEAPON) )
  547.             continue;
  548.         it->use (ent, it);
  549.         if (cl->pers.weapon == it)
  550.             return;    // successful
  551.     }
  552. }
  553.  
  554. /*
  555. =================
  556. Cmd_WeapNext_f
  557. =================
  558. */
  559. void Cmd_WeapNext_f (edict_t *ent)
  560. {
  561.     gclient_t    *cl;
  562.     int            i, index;
  563.     gitem_t        *it;
  564.     int            selected_weapon;
  565.  
  566.     cl = ent->client;
  567.  
  568.     if (!cl->pers.weapon)
  569.         return;
  570.  
  571.     selected_weapon = ITEM_INDEX(cl->pers.weapon);
  572.  
  573.     // scan  for the next valid one
  574.     for (i=1 ; i<=MAX_ITEMS ; i++)
  575.     {
  576.         index = (selected_weapon + MAX_ITEMS - i)%MAX_ITEMS;
  577.         if (!cl->pers.inventory[index])
  578.             continue;
  579.         it = &itemlist[index];
  580.         if (!it->use)
  581.             continue;
  582.         if (! (it->flags & IT_WEAPON) )
  583.             continue;
  584.         it->use (ent, it);
  585.         if (cl->pers.weapon == it)
  586.             return;    // successful
  587.     }
  588. }
  589.  
  590. /*
  591. =================
  592. Cmd_WeapLast_f
  593. =================
  594. */
  595. void Cmd_WeapLast_f (edict_t *ent)
  596. {
  597.     gclient_t    *cl;
  598.     int            index;
  599.     gitem_t        *it;
  600.  
  601.     cl = ent->client;
  602.  
  603.     if (!cl->pers.weapon || !cl->pers.lastweapon)
  604.         return;
  605.  
  606.     index = ITEM_INDEX(cl->pers.lastweapon);
  607.     if (!cl->pers.inventory[index])
  608.         return;
  609.     it = &itemlist[index];
  610.     if (!it->use)
  611.         return;
  612.     if (! (it->flags & IT_WEAPON) )
  613.         return;
  614.     it->use (ent, it);
  615. }
  616.  
  617. /*
  618. =================
  619. Cmd_InvDrop_f
  620. =================
  621. */
  622. void Cmd_InvDrop_f (edict_t *ent)
  623. {
  624.     gitem_t        *it;
  625.  
  626.     ValidateSelectedItem (ent);
  627.  
  628.     if (ent->client->pers.selected_item == -1)
  629.     {
  630.         gi.cprintf (ent, PRINT_HIGH, "No item to drop.\n");
  631.         return;
  632.     }
  633.  
  634.     it = &itemlist[ent->client->pers.selected_item];
  635.     if (!it->drop)
  636.     {
  637.         gi.cprintf (ent, PRINT_HIGH, "Item is not dropable.\n");
  638.         return;
  639.     }
  640.     it->drop (ent, it);
  641. }
  642.  
  643. /*
  644. =================
  645. Cmd_Kill_f
  646. =================
  647. */
  648. void Cmd_Kill_f (edict_t *ent)
  649. {
  650.     if((level.time - ent->client->respawn_time) < 5)
  651.         return;
  652.     ent->flags &= ~FL_GODMODE;
  653.     ent->health = 0;
  654.     meansOfDeath = MOD_SUICIDE;
  655.     player_die (ent, ent, ent, 100000, vec3_origin);
  656. }
  657.  
  658. /*
  659. =================
  660. Cmd_PutAway_f
  661. =================
  662. */
  663. void Cmd_PutAway_f (edict_t *ent)
  664. {
  665.     ent->client->showscores = false;
  666.     ent->client->showhelp = false;
  667.     ent->client->showinventory = false;
  668. }
  669.  
  670.  
  671. int PlayerSort (void const *a, void const *b)
  672. {
  673.     int        anum, bnum;
  674.  
  675.     anum = *(int *)a;
  676.     bnum = *(int *)b;
  677.  
  678.     anum = game.clients[anum].ps.stats[STAT_FRAGS];
  679.     bnum = game.clients[bnum].ps.stats[STAT_FRAGS];
  680.  
  681.     if (anum < bnum)
  682.         return -1;
  683.     if (anum > bnum)
  684.         return 1;
  685.     return 0;
  686. }
  687.  
  688. /*
  689. =================
  690. Cmd_Players_f
  691. =================
  692. */
  693. void Cmd_Players_f (edict_t *ent)
  694. {
  695.     int        i;
  696.     int        count;
  697.     char    small[64];
  698.     char    large[1280];
  699.     int        index[256];
  700.  
  701.     count = 0;
  702.     for (i = 0 ; i < maxclients->value ; i++)
  703.         if (game.clients[i].pers.connected)
  704.         {
  705.             index[count] = i;
  706.             count++;
  707.         }
  708.  
  709.     // sort by frags
  710.     qsort (index, count, sizeof(index[0]), PlayerSort);
  711.  
  712.     // print information
  713.     large[0] = 0;
  714.  
  715.     for (i = 0 ; i < count ; i++)
  716.     {
  717.         Com_sprintf (small, sizeof(small), "%3i %s\n",
  718.             game.clients[index[i]].ps.stats[STAT_FRAGS],
  719.             game.clients[index[i]].pers.netname);
  720.         if (strlen (small) + strlen(large) > sizeof(large) - 100 )
  721.         {    // can't print all of them in one packet
  722.             strcat (large, "...\n");
  723.             break;
  724.         }
  725.         strcat (large, small);
  726.     }
  727.  
  728.     gi.cprintf (ent, PRINT_HIGH, "%s\n%i players\n", large, count);
  729. }
  730.  
  731. /*
  732. =================
  733. Cmd_Wave_f
  734. =================
  735. */
  736. void Cmd_Wave_f (edict_t *ent)
  737. {
  738.     int        i;
  739.  
  740.     i = atoi (gi.argv(1));
  741.  
  742.     // can't wave when ducked
  743.     if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
  744.         return;
  745.  
  746.     if (ent->client->anim_priority > ANIM_WAVE)
  747.         return;
  748.  
  749.     ent->client->anim_priority = ANIM_WAVE;
  750.  
  751.     switch (i)
  752.     {
  753.     case 0:
  754.         gi.cprintf (ent, PRINT_HIGH, "flipoff\n");
  755.         ent->s.frame = FRAME_flip01-1;
  756.         ent->client->anim_end = FRAME_flip12;
  757.         break;
  758.     case 1:
  759.         gi.cprintf (ent, PRINT_HIGH, "salute\n");
  760.         ent->s.frame = FRAME_salute01-1;
  761.         ent->client->anim_end = FRAME_salute11;
  762.         break;
  763.     case 2:
  764.         gi.cprintf (ent, PRINT_HIGH, "taunt\n");
  765.         ent->s.frame = FRAME_taunt01-1;
  766.         ent->client->anim_end = FRAME_taunt17;
  767.         break;
  768.     case 3:
  769.         gi.cprintf (ent, PRINT_HIGH, "wave\n");
  770.         ent->s.frame = FRAME_wave01-1;
  771.         ent->client->anim_end = FRAME_wave11;
  772.         break;
  773.     case 4:
  774.     default:
  775.         gi.cprintf (ent, PRINT_HIGH, "point\n");
  776.         ent->s.frame = FRAME_point01-1;
  777.         ent->client->anim_end = FRAME_point12;
  778.         break;
  779.     }
  780. }
  781.  
  782. /*
  783. ==================
  784. Cmd_Say_f
  785. ==================
  786. */
  787. void Cmd_Say_f (edict_t *ent, qboolean team, qboolean arg0)
  788. {
  789.     int        i, j;
  790.     edict_t    *other;
  791.     char    *p;
  792.     char    text[2048];
  793.     gclient_t *cl;
  794.  
  795.     if (gi.argc () < 2 && !arg0)
  796.         return;
  797.  
  798.     if (!((int)(dmflags->value) & (DF_MODELTEAMS | DF_SKINTEAMS)))
  799.         team = false;
  800.  
  801.     if (team)
  802.         Com_sprintf (text, sizeof(text), "(%s): ", ent->client->pers.netname);
  803.     else
  804.         Com_sprintf (text, sizeof(text), "%s: ", ent->client->pers.netname);
  805.  
  806.     if (arg0)
  807.     {
  808.         strcat (text, gi.argv(0));
  809.         strcat (text, " ");
  810.         strcat (text, gi.args());
  811.     }
  812.     else
  813.     {
  814.         p = gi.args();
  815.  
  816.         if (*p == '"')
  817.         {
  818.             p++;
  819.             p[strlen(p)-1] = 0;
  820.         }
  821.         strcat(text, p);
  822.     }
  823.  
  824.     // don't let text be too long for malicious reasons
  825.     if (strlen(text) > 150)
  826.         text[150] = 0;
  827.  
  828.     strcat(text, "\n");
  829.  
  830.     if (flood_msgs->value) {
  831.         cl = ent->client;
  832.  
  833.         if (level.time < cl->flood_locktill) {
  834.             gi.cprintf(ent, PRINT_HIGH, "You can't talk for %d more seconds\n",
  835.                 (int)(cl->flood_locktill - level.time));
  836.             return;
  837.         }
  838.         i = cl->flood_whenhead - flood_msgs->value + 1;
  839.         if (i < 0)
  840.             i = (sizeof(cl->flood_when)/sizeof(cl->flood_when[0])) + i;
  841.         if (cl->flood_when[i] && 
  842.             level.time - cl->flood_when[i] < flood_persecond->value) {
  843.             cl->flood_locktill = level.time + flood_waitdelay->value;
  844.             gi.cprintf(ent, PRINT_CHAT, "Flood protection:  You can't talk for %d seconds.\n",
  845.                 (int)flood_waitdelay->value);
  846.             return;
  847.         }
  848.         cl->flood_whenhead = (cl->flood_whenhead + 1) %
  849.             (sizeof(cl->flood_when)/sizeof(cl->flood_when[0]));
  850.         cl->flood_when[cl->flood_whenhead] = level.time;
  851.     }
  852.  
  853.     if (dedicated->value)
  854.         gi.cprintf(NULL, PRINT_CHAT, "%s", text);
  855.  
  856.     for (j = 1; j <= game.maxclients; j++)
  857.     {
  858.         other = &g_edicts[j];
  859.         if (!other->inuse)
  860.             continue;
  861.         if (!other->client)
  862.             continue;
  863.         if (team)
  864.         {
  865.             if (!OnSameTeam(ent, other))
  866.                 continue;
  867.         }
  868.         gi.cprintf(other, PRINT_CHAT, "%s", text);
  869.     }
  870. }
  871.  
  872. void Cmd_PlayerList_f(edict_t *ent)
  873. {
  874.     int i;
  875.     char st[80];
  876.     char text[1400];
  877.     edict_t *e2;
  878.  
  879.     // connect time, ping, score, name
  880.     *text = 0;
  881.     for (i = 0, e2 = g_edicts + 1; i < maxclients->value; i++, e2++) {
  882.         if (!e2->inuse)
  883.             continue;
  884.  
  885.         Com_sprintf(st, sizeof(st), "%02d:%02d %4d %3d %s%s\n",
  886.             (level.framenum - e2->client->resp.enterframe) / 600,
  887.             ((level.framenum - e2->client->resp.enterframe) % 600)/10,
  888.             e2->client->ping,
  889.             e2->client->resp.score,
  890.             e2->client->pers.netname,
  891.             e2->client->resp.spectator ? " (spectator)" : "");
  892.         if (strlen(text) + strlen(st) > sizeof(text) - 50) {
  893.             sprintf(text+strlen(text), "And more...\n");
  894.             gi.cprintf(ent, PRINT_HIGH, "%s", text);
  895.             return;
  896.         }
  897.         strcat(text, st);
  898.     }
  899.     gi.cprintf(ent, PRINT_HIGH, "%s", text);
  900. }
  901.  
  902.  
  903. /*
  904. =================
  905. ClientCommand
  906. =================
  907. */
  908. void ClientCommand (edict_t *ent)
  909. {
  910.     char    *cmd;
  911.  
  912.     if (!ent->client)
  913.         return;        // not fully in game yet
  914.  
  915.     cmd = gi.argv(0);
  916.  
  917.     if (Q_stricmp (cmd, "players") == 0)
  918.     {
  919.         Cmd_Players_f (ent);
  920.         return;
  921.     }
  922.     if (Q_stricmp (cmd, "say") == 0)
  923.     {
  924.         Cmd_Say_f (ent, false, false);
  925.         return;
  926.     }
  927.     if (Q_stricmp (cmd, "say_team") == 0)
  928.     {
  929.         Cmd_Say_f (ent, true, false);
  930.         return;
  931.     }
  932.     if (Q_stricmp (cmd, "score") == 0)
  933.     {
  934.         Cmd_Score_f (ent);
  935.         return;
  936.     }
  937.     if (Q_stricmp (cmd, "help") == 0)
  938.     {
  939.         Cmd_Help_f (ent);
  940.         return;
  941.     }
  942.  
  943.     if (level.intermissiontime)
  944.         return;
  945.  
  946.     if (Q_stricmp (cmd, "use") == 0)
  947.         Cmd_Use_f (ent);
  948.     else if (Q_stricmp (cmd, "drop") == 0)
  949.         Cmd_Drop_f (ent);
  950.     else if (Q_stricmp (cmd, "give") == 0)
  951.         Cmd_Give_f (ent);
  952.     else if (Q_stricmp (cmd, "god") == 0)
  953.         Cmd_God_f (ent);
  954.     else if (Q_stricmp (cmd, "notarget") == 0)
  955.         Cmd_Notarget_f (ent);
  956.     else if (Q_stricmp (cmd, "noclip") == 0)
  957.         Cmd_Noclip_f (ent);
  958.     else if (Q_stricmp (cmd, "inven") == 0)
  959.         Cmd_Inven_f (ent);
  960.     else if (Q_stricmp (cmd, "invnext") == 0)
  961.         SelectNextItem (ent, -1);
  962.     else if (Q_stricmp (cmd, "invprev") == 0)
  963.         SelectPrevItem (ent, -1);
  964.     else if (Q_stricmp (cmd, "invnextw") == 0)
  965.         SelectNextItem (ent, IT_WEAPON);
  966.     else if (Q_stricmp (cmd, "invprevw") == 0)
  967.         SelectPrevItem (ent, IT_WEAPON);
  968.     else if (Q_stricmp (cmd, "invnextp") == 0)
  969.         SelectNextItem (ent, IT_POWERUP);
  970.     else if (Q_stricmp (cmd, "invprevp") == 0)
  971.         SelectPrevItem (ent, IT_POWERUP);
  972.     else if (Q_stricmp (cmd, "invuse") == 0)
  973.         Cmd_InvUse_f (ent);
  974.     else if (Q_stricmp (cmd, "invdrop") == 0)
  975.         Cmd_InvDrop_f (ent);
  976.     else if (Q_stricmp (cmd, "weapprev") == 0)
  977.         Cmd_WeapPrev_f (ent);
  978.     else if (Q_stricmp (cmd, "weapnext") == 0)
  979.         Cmd_WeapNext_f (ent);
  980.     else if (Q_stricmp (cmd, "weaplast") == 0)
  981.         Cmd_WeapLast_f (ent);
  982.     else if (Q_stricmp (cmd, "kill") == 0)
  983.         Cmd_Kill_f (ent);
  984.     else if (Q_stricmp (cmd, "putaway") == 0)
  985.         Cmd_PutAway_f (ent);
  986.     else if (Q_stricmp (cmd, "wave") == 0)
  987.         Cmd_Wave_f (ent);
  988.     else if (Q_stricmp(cmd, "playerlist") == 0)
  989.         Cmd_PlayerList_f(ent);
  990.     else if (Q_stricmp (cmd, "flashlight") == 0)
  991.         FL_make (ent);
  992.     else    // anything that doesn't match a command will be a chat
  993.         Cmd_Say_f (ent, false, true);
  994.  
  995. }
  996.